/**
 * 
 */
package inge_soft.gestoriusNuevo.business.service.implementation;

import inge_soft.gestoriusNuevo.persistence.DAO.Exceptions.Implementation.UsuarioInexistenteException;
import inge_soft.gestoriusNuevo.persistence.DAO.abstraction.IUsuarioRegistradoDAO;
import inge_soft.gestoriusNuevo.persistence.entity.implementation.UsuarioRegistrado;
import inge_soft.gestoriusNuevo.support.Global;
import inge_soft.gestoriusNuevo.support.UsuarioSistema;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

/**
 * A custom UserDetailsService implementation to adapt to extended User class.<br>
 * 
 * If you have your own user credential model and don't want to change it even a
 * bit, then instead of swapping the UserDetailService of default
 * AuthenticationProvider, you have to swap the AuthenticationProvider itself,
 * and you'll have to deal with password hashing and salting by your own.<br>
 * 
 * 
 * @author Joaquin Lima (Ian YT Tsai)
 * 
 */
public class UsuarioSistemaService implements UserDetailsService {

	@Autowired
	@Qualifier("usuarioRegistradoDAO")
	IUsuarioRegistradoDAO usuarioRegistradoDAO;

	public UserDetails loadUserByUsername(String username)
			throws UsuarioInexistenteException {

		UsuarioRegistrado userR;
		try{
			userR = usuarioRegistradoDAO.findByNick(username);
		} catch(UsuarioInexistenteException e){
			throw e;
		}
		/*
		if (userR == null) {
			System.out.println(">>> No se pudo encontrar usuarior: " + username);
			throw new UsernameNotFoundException("No se pudo encontrar usuarior: "
					+ username);
		}
		*/
		UsuarioSistema user = new UsuarioSistema(userR.getNick(),
				userR.getContrasenia(), getAuthorities(userR.getRol()));

		return user;
	}

	/**
	 * Retrieves the correct ROLE type depending on the access level, where
	 * access level is an Integer. Basically, this interprets the access value
	 * whether it's for a regular user or admin.
	 * 
	 * @param access
	 *            an integer value representing the access of the user
	 * @return collection of granted authorities
	 */
	private Collection<GrantedAuthority> getAuthorities(Integer access) {
		// Create a list of grants for this user
		List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();

		if (access.compareTo(Global.ROLE_USUARIO_REGISTRADO) >= 0) {
			// User has ROLE_USUARIO_REGISTRADO access
			authList.add(new SimpleGrantedAuthority(Global.getRole(Global.ROLE_USUARIO_REGISTRADO)));
		}

		if (access.compareTo(Global.ROLE_USUARIO_ORGANIZADOR) >= 0) {
			// User has ROLE_USUARIO_ORGANIZADOR access
			authList.add(new SimpleGrantedAuthority(Global.getRole(Global.ROLE_USUARIO_ORGANIZADOR)));
		}
		
		if (access.compareTo(Global.ROLE_USUARIO_MODERADOR) >= 0) {
			// User has ROLE_USUARIO_ORGANIZADOR access
			authList.add(new SimpleGrantedAuthority(Global.getRole(Global.ROLE_USUARIO_MODERADOR)));
		}
		
		if (access.compareTo(Global.ROLE_USUARIO_AUDITOR) >= 0) {
			// User has ROLE_USUARIO_ORGANIZADOR access
			authList.add(new SimpleGrantedAuthority(Global.getRole(Global.ROLE_USUARIO_AUDITOR)));
		}

		if (access.compareTo(Global.ROLE_USUARIO_ADMINISTRADOR) >= 0) {
			// User has ROLE_USUARIO_ORGANIZADOR access
			authList.add(new SimpleGrantedAuthority(Global.getRole(Global.ROLE_USUARIO_ADMINISTRADOR)));
			//authList.add(new GrantedAuthorityImpl("ROLE_USUARIO_ADMINISTRADOR"));
		}
		// Return list of granted authorities
		return authList;
	}
}
